﻿using System.Runtime.InteropServices;
using System.Text;

namespace System.NETool;

public static class SpanEx
{
    /// <summary>
    /// 获取数组十六进制字符串值
    /// </summary>
    /// <param name="this">数组</param>
    /// <param name="span">分隔符</param>
    /// <returns>字符串</returns>
    public static string ToHexString(this Span<byte> @this, string span = "")
        => ReadOnlySpanEx.ToHexString(@this, span);

    /// <summary>
    /// 数组转结构对象
    /// </summary>
    /// <typeparam name="T">结构类型</typeparam>
    /// <param name="this">数组</param>
    /// <returns>转结构对象</returns>
    /// <exception cref="NullReferenceException"></exception>
    public static T ToStruct<T>(this Span<byte> @this) where T : struct
        => ReadOnlySpanEx.ToStruct<T>(@this);

    /// <summary>
    /// 将结构类型的Span转换为字节类型的Span
    /// </summary>
    /// <typeparam name="T">结构类型</typeparam>
    /// <param name="this">结构类型的Span</param>
    /// <returns>字节类型的Span</returns>
    public static Span<byte> AsBytes<T>(this Span<T> @this) where T : struct
    {
        return MemoryMarshal.AsBytes(@this);
    }

    /// <summary>
    /// 将一种结构类型的Span转换为另一种结构类型的Span
    /// </summary>
    /// <typeparam name="TFrom">源结构类型</typeparam>
    /// <typeparam name="TTo">目标结构类型</typeparam>
    /// <param name="this">源结构类型的Span</param>
    /// <returns>目标结构类型的Span</returns>
    public static Span<TTo> Cast<TFrom, TTo>(this Span<TFrom> @this) where TFrom : struct where TTo : struct
    {
        return MemoryMarshal.Cast<TFrom, TTo>(@this);
    }

    /// <summary>
    /// 打印字节数组的十六进制表示
    /// </summary>
    /// <param name="this">字节数组</param>
    /// <param name="title">标题</param>
    /// <param name="color">控制台颜色</param>
    public static void HexPrint(this Span<byte> @this, string title = "", ConsoleColor color = ConsoleColor.Blue)
    {
        ReadOnlySpanEx.HexPrint(@this, title, color);
    }

    /// <summary>
    /// ASCII编码的数组转换为英文字符串
    /// </summary>
    /// <param name="this">数组</param>
    /// <returns>结果</returns>
    public static string ToEnString(this Span<byte> @this) => Encoding.ASCII.GetString(@this).Trim('\0').Trim();

    /// <summary>
    /// 计算字节数组的MD5哈希值并返回十六进制字符串
    /// </summary>
    /// <param name="this">字节数组</param>
    /// <returns>MD5哈希值的十六进制字符串</returns>
    public static string MD5(this Span<byte> @this) => ReadOnlySpanEx.MD5(@this);

    /// <summary>
    /// 计算字节数组的SHA1哈希值并返回十六进制字符串
    /// </summary>
    /// <param name="this">字节数组</param>
    /// <returns>SHA1哈希值的十六进制字符串</returns>
    public static string SHA1(this Span<byte> @this) => ReadOnlySpanEx.SHA1(@this);

    /// <summary>
    /// 计算字节数组的SHA256哈希值并返回十六进制字符串
    /// </summary>
    /// <param name="this">字节数组</param>
    /// <returns>SHA256哈希值的十六进制字符串</returns>
    public static string SHA256(this Span<byte> @this) => ReadOnlySpanEx.SHA256(@this);

    /// <summary>
    /// 计算字节数组的SHA384哈希值并返回十六进制字符串
    /// </summary>
    /// <param name="this">字节数组</param>
    /// <returns>SHA384哈希值的十六进制字符串</returns>
    public static string SHA384(this Span<byte> @this) => ReadOnlySpanEx.SHA384(@this);

    /// <summary>
    /// 计算字节数组的SHA512哈希值并返回十六进制字符串
    /// </summary>
    /// <param name="this">字节数组</param>
    /// <returns>SHA512哈希值的十六进制字符串</returns>
    public static string SHA512(this Span<byte> @this) => ReadOnlySpanEx.SHA512(@this);

    /// <summary>
    /// 计算字节数组的SHA3_256哈希值并返回十六进制字符串
    /// </summary>
    /// <param name="this">字节数组</param>
    /// <returns>SHA3_256哈希值的十六进制字符串</returns>
    public static string SHA3_256(this Span<byte> @this) => ReadOnlySpanEx.SHA3_256(@this);

    /// <summary>
    /// 计算字节数组的SHA3_384哈希值并返回十六进制字符串
    /// </summary>
    /// <param name="this">字节数组</param>
    /// <returns>SHA3_384哈希值的十六进制字符串</returns>
    public static string SHA3_384(this Span<byte> @this) => ReadOnlySpanEx.SHA3_384(@this);

    /// <summary>
    /// 计算字节数组的SHA3_512哈希值并返回十六进制字符串
    /// </summary>
    /// <param name="this">字节数组</param>
    /// <returns>SHA3_512哈希值的十六进制字符串</returns>
    public static string SHA3_512(this Span<byte> @this) => ReadOnlySpanEx.SHA3_512(@this);

    /// <summary>
    /// 生成PBKDF2哈希字符串
    /// </summary>
    /// <param name="this">字节数组</param>
    /// <param name="iterationCount">迭代次数</param>
    /// <param name="derivedKeyLength">派生密钥长度</param>
    /// <returns>PBKDF2哈希字符串</returns>
    public static string PBKDF2(this Span<byte> @this, int iterationCount = 1000, int derivedKeyLength = 32) =>
        ReadOnlySpanEx.PBKDF2(@this, iterationCount, derivedKeyLength);

    /// <summary>
    /// 验证PBKDF2哈希字符串
    /// </summary>
    /// <param name="this">字节数组</param>
    /// <param name="hash">PBKDF2哈希字符串</param>
    /// <param name="iterationCount">迭代次数</param>
    /// <returns>验证结果</returns>
    public static bool PBKDF2Verify(this Span<byte> @this, string hash, int iterationCount = 1000) =>
        ReadOnlySpanEx.PBKDF2Verify(@this, hash, iterationCount);

    /// <summary>
    /// 使用AES算法加密字节数组
    /// </summary>
    /// <param name="this">要加密的明文字节数组</param>
    /// <param name="key">加密密钥</param>
    /// <param name="iv">初始化向量</param>
    /// <returns>加密后的字节数组</returns>
    public static byte[] AesEncrypt(this Span<byte> @this, string key = "", string iv = "") =>
        ReadOnlySpanEx.AesEncrypt(@this, key, iv);

    /// <summary>
    /// 使用AES算法解密字节数组
    /// </summary>
    /// <param name="this">要解密的字节数组</param>
    /// <param name="key">解密密钥</param>
    /// <param name="iv">初始化向量</param>
    /// <returns>解密后的字节数组</returns>
    public static byte[] AesDecrypt(this Span<byte> @this, string key = "", string iv = "") =>
        ReadOnlySpanEx.AesDecrypt(@this, key, iv);

    /// <summary>
    /// 使用DES算法加密字节数组
    /// </summary>
    /// <param name="this">要加密的明文字节数组</param>
    /// <param name="key">加密密钥</param>
    /// <param name="iv">初始化向量</param>
    /// <returns>加密后的字节数组</returns>
    public static byte[] DesEncrypt(this Span<byte> @this, string key = "", string iv = "") =>
        ReadOnlySpanEx.DesEncrypt(@this, key, iv);

    /// <summary>
    /// 使用DES算法解密字节数组
    /// </summary>
    /// <param name="this">要解密的字节数组</param>
    /// <param name="key">解密密钥</param>
    /// <param name="iv">初始化向量</param>
    /// <returns>解密后的字节数组</returns>
    public static byte[] DesDecrypt(this Span<byte> @this, string key = "", string iv = "") =>
        ReadOnlySpanEx.DesDecrypt(@this, key, iv);

    /// <summary>
    /// 使用GZip算法压缩字节数组
    /// </summary>
    /// <param name="this">要压缩的字节数组</param>
    /// <returns>压缩后的字节数组</returns>
    public static byte[] GZipCompress(this Span<byte> @this) => ReadOnlySpanEx.GZipCompress(@this);

    /// <summary>
    /// 使用GZip算法解压缩字节数组
    /// </summary>
    /// <param name="this">要解压缩的字节数组</param>
    /// <returns>解压缩后的字节数组</returns>
    public static byte[] GZipDecompress(this Span<byte> @this) => ReadOnlySpanEx.GZipDecompress(@this);

    /// <summary>
    /// 使用Deflate算法压缩字节数组
    /// </summary>
    /// <param name="this">要压缩的字节数组</param>
    /// <returns>压缩后的字节数组</returns>
    public static byte[] ZipCompress(this Span<byte> @this) => ReadOnlySpanEx.ZipCompress(@this);

    /// <summary>
    /// 使用Deflate算法解压缩字节数组
    /// </summary>
    /// <param name="this">要解压缩的字节数组</param>
    /// <returns>解压缩后的字节数组</returns>
    public static byte[] ZipDecompress(this Span<byte> @this) => ReadOnlySpanEx.ZipDecompress(@this);
}
